import type { Block, Line, Point } from '@/types';
import { real2Draw } from '@/utils/coordTransform';
import { useCanvasStore } from '@/store/modules/canvas';

/**
 * 绘制网格
 */
export function drawGrid(
    ctx: CanvasRenderingContext2D,
    canvas: HTMLCanvasElement,
    canvasStore: ReturnType<typeof useCanvasStore>
): void {
    const { scale, origin, currentGridSize: gridSize } = canvasStore;
    const { width, height } = canvas;

    ctx.save();

    // 计算网格线的间隔（绘制坐标）
    const gridDrawSize = gridSize * scale;

    // 计算可见区域内的第一条和最后一条网格线
    const startX = Math.floor(-origin.x / gridDrawSize) * gridDrawSize;
    const startY = Math.floor(-origin.y / gridDrawSize) * gridDrawSize;

    const endX = width + (gridDrawSize - (width % gridDrawSize));
    const endY = height + (gridDrawSize - (height % gridDrawSize));

    // 绘制水平线
    ctx.strokeStyle = '#e0e0e0';
    ctx.lineWidth = 1;

    for (let y = startY; y < endY; y += gridDrawSize) {
        ctx.beginPath();
        ctx.moveTo(0, y + origin.y);
        ctx.lineTo(width, y + origin.y);
        ctx.stroke();
    }

    // 绘制垂直线
    for (let x = startX; x < endX; x += gridDrawSize) {
        ctx.beginPath();
        ctx.moveTo(x + origin.x, 0);
        ctx.lineTo(x + origin.x, height);
        ctx.stroke();
    }

    // 绘制原点十字线
    const originDrawPos = real2Draw(scale, origin, { x: 0, y: 0 });

    ctx.strokeStyle = '#999';
    ctx.lineWidth = 1;

    // 水平线
    ctx.beginPath();
    ctx.moveTo(0, originDrawPos.y);
    ctx.lineTo(width, originDrawPos.y);
    ctx.stroke();

    // 垂直线
    ctx.beginPath();
    ctx.moveTo(originDrawPos.x, 0);
    ctx.lineTo(originDrawPos.x, height);
    ctx.stroke();

    ctx.restore();
}

/**
 * 绘制块(车辆)
 */
export function drawBlock(
    ctx: CanvasRenderingContext2D,
    block: Block,
    canvasStore: ReturnType<typeof useCanvasStore>
): void {
    const { scale, origin } = canvasStore;
    const drawPos = real2Draw(scale, origin, { x: block.x, y: block.y });

    ctx.save();

    // 平移到块的位置
    ctx.translate(drawPos.x, drawPos.y);

    // 旋转到块的朝向
    ctx.rotate((block.heading - 90) * Math.PI / 180);

    // 绘制碰撞体（矩形）
    const { l1, l2 } = block.collision;
    const halfL1 = (l1 / 2) * scale;
    const halfL2 = (l2 / 2) * scale;

    ctx.fillStyle = block.color;
    ctx.strokeStyle = '#333';
    ctx.lineWidth = 1;

    ctx.beginPath();
    ctx.rect(-halfL1, -halfL2, l1 * scale, l2 * scale);
    ctx.fill();
    ctx.stroke();

    // 绘制图片
    ctx.drawImage(block.source.img, -halfL1, -halfL2, l1 * scale, l2 * scale)

    // 绘制朝向指示器
    ctx.strokeStyle = '#fff';
    ctx.lineWidth = 2;

    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(halfL1, 0);
    ctx.stroke();

    // 绘制名称
    ctx.fillStyle = '#fff';
    ctx.font = '12px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(block.name, 0, 0);

    ctx.restore();
}

/**
 * 绘制选中块的高亮效果
 */
export function drawSelectedBlock(
    ctx: CanvasRenderingContext2D,
    block: Block,
    canvasStore: ReturnType<typeof useCanvasStore>
): void {
    const { scale, origin } = canvasStore;
    const drawPos = real2Draw(scale, origin, { x: block.x, y: block.y });

    ctx.save();

    // 平移到块的位置
    ctx.translate(drawPos.x, drawPos.y);

    // 旋转到块的朝向
    ctx.rotate((block.heading-90) * Math.PI / 180);

    // 绘制选中边框（虚线）
    const { l1, l2 } = block.collision;
    const halfL1 = (l1 / 2 + 0.2) * scale; // 稍微大一点
    const halfL2 = (l2 / 2 + 0.2) * scale;

    ctx.strokeStyle = '#ff0000';
    ctx.lineWidth = 2;
    ctx.setLineDash([5, 3]);

    ctx.beginPath();
    ctx.rect(-halfL1, -halfL2, (l1 + 0.4) * scale, (l2 + 0.4) * scale);
    ctx.stroke();

    ctx.setLineDash([]); // 重置虚线样式

    ctx.restore();
}

/**
 * 绘制线段
 */
export function drawLine(
    ctx: CanvasRenderingContext2D,
    line: Line,
    scale: number,
    origin: Point
): void {
    const start = real2Draw(scale, origin, line.start);
    const end = real2Draw(scale, origin, line.end);

    ctx.save();

    ctx.strokeStyle = line.color || '#333';
    ctx.lineWidth = line.width || 1;

    ctx.beginPath();
    ctx.moveTo(start.x, start.y);
    ctx.lineTo(end.x, end.y);
    ctx.stroke();

    ctx.restore();
}
